grammar Antlr;

options {
	language=Java;
	output=AST;
}

@header{
	package it.uniroma2.art.coda.projectionrule.antlr;
	import it.uniroma2.art.coda.projectionrule.antlr.AntlrParserRuntimeException;
}
 
@lexer::header {
  package it.uniroma2.art.coda.projectionrule.antlr;
}


@lexer::members {
  @Override
  public void reportError(RecognitionException e) {
  	System.out.println("&&& Lexer::reportError"); // da cancellare
  	String text = ((UnwantedTokenException)e).getUnexpectedToken().getText();
	 	int line = ((UnwantedTokenException)e).getUnexpectedToken().getLine();
	 	int pos = ((UnwantedTokenException)e).getUnexpectedToken().getCharPositionInLine();
	 	String msg = "Lexer error with text = "+text+" at line "+line+" and char "+pos;
	 	throw new AntlrParserRuntimeException(msg);
  }
}


@members {
@Override
  public void reportError(RecognitionException e) {
  	String msg = "Parser error";
	 	if(e instanceof UnwantedTokenException){
		 	String text = ((UnwantedTokenException)e).getUnexpectedToken().getText();
		 	int line = ((UnwantedTokenException)e).getUnexpectedToken().getLine();
		 	int pos = ((UnwantedTokenException)e).getUnexpectedToken().getCharPositionInLine();
		 	msg += " with text = "+text+" at line "+line+" and char "+pos;
	 	}
	 	else if(e instanceof MismatchedTokenException){
	 		System.out.println(((MismatchedTokenException)e).getLocalizedMessage()); // da cancellare
	 	}
	 	else{
	 		System.out.println("&&& e.getClass() = "+e.getClass()); // da cancellare
	 	}
	 	//System.out.println("&&& Problem with text = "+text+" at line "+line+" and char "+pos); // da cancellare
	 	
	 	throw new AntlrParserRuntimeException(msg);
	  //throw new IllegalArgumentException(e);
  }

}


/*@rulecatch {
catch (IllegalArgumentException e)
{
		throw e;
}
}*/





 

prRules
	:		prefixRule*	prRule+ -> ^(ROOT ^( PREFIXPART prefixRule*) ^(PRRules prRule+) )
	;

	

prefixRule
	: prefix '='  namespace ';' -> ^(PREFIX prefix ^(NAMESPACE namespace) )
	;

prRule
	:		RULE uimaTypePR (ID ':' idVal=word)? Conf? dependsOn? imports? '{'
			 alias? nodes? graph? where? parameters? ';'? '}'
			-> ^(PRRule (^(CONF Conf))? uimaTypePR (^(ID $idVal))? dependsOn? imports? 
				alias? nodes? graph? where? parameters?)
	;

//dependency part
dependsOn
	:		DependsOn (dependency ','? )+ -> ^(DependsOn dependency+)
	;
	
imports
	:		Imports (dependency ','? )+ -> ^(Imports dependency+)
	;

dependency
	:		DependType1 '(' idRule=word ')' -> ^(DependType1 $idRule)
	|		DependType2	'('	idRule=word ',' uimaTypePR ')' ->	^(DependType2 $idRule uimaTypePR)
	|		DependType3	'('	idRule1=word ',' idRule2=word ','  idRule3=word ')' ->	^(DependType3 $idRule1 $idRule2 $idRule3)
	|		DependTypeMult	'('	idRule1=word ',' (idRuleMult=word ',')+  idRule3=word ')' ->	^(DependTypeMult $idRule1 $idRuleMult+ $idRule3)
	
	;

//alias part
alias
	:		ALIAS '=' '{' singleAlias+ '}' -> ^(ALIAS singleAlias+)
	|		ALIAS '=' '{' '}' -> NOALIAS
	;
	
singleAlias
	:		idAlias=word uimaTypeAndFeats
			-> ^(SINGLEALIAS ^(ID $idAlias) uimaTypeAndFeats)
	;

// nodes part
nodes
	:		NODES '=' '{' node+ '}' -> ^(NODES node+)
	|		NODES '=' '{' '}' -> NONODE
	;

node
	:		idNode=word type=projType uimaTypeAndFeats
			-> ^(NODE ^(ID $idNode) ^(TYPE $type)  uimaTypeAndFeats)
	| 	idNode=word type=projType condIf 
			-> ^(NODE ^(ID $idNode) ^(TYPE $type)  condIf)
	;

projType
	:		('uri'|('plainLiteral'(lang)?)|('literal' ('(' LITERALTYPE ')') ))
	;

lang:	'(' word ')';


nodeIfElseValue
	:		uimaTypeAndFeats -> uimaTypeAndFeats
	| ontClass -> ^(ONTORES ontClass)
	| ontProperty -> ^(ONTORES ontProperty)
	;

condIf
	:		IF condValueAndUIMAType	condElseIf* condElse?
			->	^(COND ^(IF condValueAndUIMAType) condElseIf* condElse? )
	;

condValueAndUIMAType
	:		'(' condBool ')' '{' nodeIfElseValue '}' 
			-> condBool nodeIfElseValue
	;

condBool
	:		'$' aliasName=word CONDOP (val+=word)+
			-> ^(CONDBOOL $aliasName CONDOP $val+)
	;

condElseIf
	:		'else' 'if' condValueAndUIMAType -> ^(ELSEIF condValueAndUIMAType)
	;

condElse
	:		'else' '{' nodeIfElseValue '}' -> ^(ELSE nodeIfElseValue)
	;

// graph part
graph
	:		GRAPH '=' '{' singleTriple+ '}' -> ^(GRAPH singleTriple+)
	;

singleTriple
	:		tripleSubj  triplePred  tripleObj '.' 
			-> ^(TRIPLE ^(SUBJ tripleSubj) ^(PRED triplePred) ^(OBJ tripleObj))
	|		OPTIONAL '{' tripleSubj  triplePred  tripleObj '.'? '}''.'?
			-> ^(OPTIONALTRIPLE ^(SUBJ tripleSubj) ^(PRED triplePred) ^(OBJ tripleObj))
	;
	
tripleSubj
	:		tripleElem|ontClass|ontProperty|valueDatatype
	;	

triplePred
	:		tripleElem|ontProperty|ABBR
	;
	
tripleObj
	:		tripleElem|ontClass|ontProperty|valueDatatype
	;
			
tripleElem
	:		(refId|var)
	;			
			
refId
	:		'$' word -> ^(PLACEHOLDER word)
	|		'$' idPR=word ':' nodeId=word -> ^(PLACEHOLDER $idPR $nodeId)
	;
	
var
	:		'?' word -> ^(VAR word)
	;

//where part (reference to the graph part)
where
	:		WHERE '=' '{' singleTriple+ '}' -> ^(WHERE singleTriple+)
	;

//parameters part
parameters
	: 	PARAMETERS '=' '{' (parameterNameValue (',' parameterNameValue)*)?   '}' -> ^(PARAMETERSLIST parameterNameValue+)
	;
	
parameterNameValue
	:		name=parameterName ('=' val=parameterValue)? -> ^(PARAMETER ^(PARAMETERNAME $name) ^(PARAMETERVALUE $val)?)
	;

namespace: ('http'|'ftp')'://' word(('/'|'.')word)* ('#'|'/'); 
prefix: SmallWord;
uimaType:	SmallWord ('.'SmallWord)* ('.'CapitalWord);
uimaFeat:	 SmallWord ('['Number ']')?;
uimaTypePR: uimaType -> ^(UIMATYPE uimaType);
uimaTypeAndFeats: '_'uimaType (':' feat+=uimaFeat ('/' feat+=uimaFeat)*)?
		-> ^(UIMATYPEANDFEATS ^(UIMATYPE uimaType) ^(UIMAFEAT  $feat+)? );
ontClass
	:		'<' namespace CapitalWord '>' -> namespace CapitalWord
	|		prefix ':'	CapitalWord
	;
ontProperty
	:		'<' namespace  SmallWord '>' -> namespace SmallWord
	|		prefix ':' SmallWord
	;
valueDatatype
	:		Number -> ^(DATATYPEVALUE Number)
	|		'\"' word+ '\"' -> ^(DATATYPEVALUE word+)
	;

//attributeNaV: word ('.' word)*;
parameterName: SmallWord;
parameterValue: uimaType(':'uimaFeat)* | ontClass | ontProperty | word;

word: SmallWord | CapitalWord | Number | numberWord | Conf;

numberWord: Number ('_'|'-')? ( CapitalWord | SmallWord );

//TOKEN list (the order is the one in which the appear in the rules)
ROOT: 							'root';

PREFIXPART: 				'prefixpart';
PREFIX: 						'prefix';
NAMESPACE: 					'namespace';

PRRules: 						'prRules';
PRRule: 						'prRule';
RULE:								'rule';
UIMATYPE: 					'uimaType';
CONF: 							'conf';
ID:									'id';

DependsOn:					'dependsOn';
Imports:						'imports';
DependType1: 				'last'; // (|'next'|'enclose'); // add new dependtype
DependType2:	 			'previous'; // add new dependtype
DependType3:	 			'notAvailable';
DependTypeMult:			'lastOneOf'; // add new dependtype

ALIAS:							'alias';
NOALIAS:						'noalias';
SINGLEALIAS:				'singleAlias';

NODES:							'nodes';
NONODE: 						'nonode';
NODE:								'node';
TYPE:								'type';
LITERALTYPE: 				('xsd:string'|'xsd:anyURI'|'xsd:integer'|'xsd:float');  //TODO add all the possibile type and be carefull with URI vs. prefix 
COND:								'cond';
CONDOP:							('=='|'!=');
IF:									'if';
ELSEIF:							'elseif';
ELSE:								'else';
CONDBOOL:						'condBool';
UIMATYPEANDFEATS:		'uimaTypeAndFeatures';
UIMAFEAT: 					'uimaFeat';
ONTORES:						'ontoRes';

GRAPH: 							'graph';
NOGRAPH:						'nograph';
OPTIONAL:						('OPTIONAL'|'optional');
TRIPLE: 						'triple';
OPTIONALTRIPLE:			'optionalTriple';
SUBJ: 							'subj';
PRED: 							'pred';
OBJ: 								'obj';
DATATYPEVALUE:			'datatypeValue';
PLACEHOLDER:				'placeholder';
VAR:								'var';
ABBR:								'a'; // add other abbreviation if needed

WHERE:							'where';
NOWHERE:						'nowhere';

PARAMETERS: 				'parameters';
PARAMETERSLIST: 		'parametersList';
PARAMETER: 					'parameter';
PARAMETERNAME: 			'parameterName';
PARAMETERVALUE: 		'parameterValue';
 
Conf: ('0.'('0'..'9')+ )| ('1.0');
Number: ('0'..'9')+;
CapitalWord :  	('A'..'Z')('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'-')*;
SmallWord:			('a'..'z')('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'-')*;

WS: 		(' ' | '\t' | '\f' |'\r')+ {$channel=HIDDEN;};
NEWLINE: 	'\n' {$channel=HIDDEN;};
COMMENT: '//' .* ('\n' | '\r') {$channel=HIDDEN;};
MULTILINE_COMMENT:  '/*' .* '*/' {$channel=HIDDEN;};
//PropertyType:				('DataType'|'Object'|'Annotation');
//PRClass: 'prClass';
//PRProperty: 'property';
//ONTCLASS: 					'ontClass';
//ONTOPROPERTY: 			'ontProperty';
//OTHERFEATURES: 			'features';
//OTHERFEATURESLIST: 	'otherFeaturesList';
//FEATUREPROJ: 				'featureProjection';
//TYPEFEATURES: 			'typeFeatures';

 

  
